using DotNetOpenAuth.AspNet;
using Nop.Core;
using Nop.Core.Domain.Customers;
using Nop.Plugin.Misc.WebServices.Services;
using Nop.Services.Authentication.External;
using System;
using System.Collections.Generic;

namespace Nop.Plugin.Misc.WebServices.Core
{
    public class FacebookProviderAuthorizer : IAndroidProviderFacebookAuthorizer
    {
        #region Fields

        private readonly IAppExternalAuthorizer _authorizer;
        private readonly ExternalAuthenticationSettings _externalAuthenticationSettings;
     
        private readonly IWebHelper _webHelper;
      

        #endregion

        #region Ctor

        public FacebookProviderAuthorizer(IAppExternalAuthorizer authorizer,
            ExternalAuthenticationSettings externalAuthenticationSettings,
        
            IWebHelper webHelper)
        {
            this._authorizer = authorizer;
            this._externalAuthenticationSettings = externalAuthenticationSettings;
            this._webHelper = webHelper;
        }

        #endregion

        #region Utilities

     
        public AuthorizeState VerifyAuthentication(string id, string username, string name, string gender)
        {
            bool isSuccess = true;
            if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(username))
            {
                var state = new AuthorizeState(null, OpenAuthenticationStatus.Error);
                var error =  "Unknown error";
                state.AddError(error);
                return null;
            }
            else
            {
                IDictionary<string, string> extraData = new Dictionary<string, string>();
                extraData.Add("id",id);
                extraData.Add("username", username);
                extraData.Add("name", name);
                extraData.Add("link", "");
                extraData.Add("gender", gender);
                extraData.Add("accesstoken",  Convert.ToBase64String(Guid.NewGuid().ToByteArray()));

                AuthenticationResult authResult = new AuthenticationResult(isSuccess,"facebook",id,username,extraData);

                if (!authResult.ExtraData.ContainsKey("id"))
                    throw new Exception("Authentication result does not contain id data");

                if (!authResult.ExtraData.ContainsKey("accesstoken"))
                    throw new Exception("Authentication result does not contain accesstoken data");
                var parameters = new AndroidAuthenticationParameters(Provider.SystemName)
                {
                    ExternalIdentifier = authResult.ProviderUserId,
                    OAuthToken = authResult.ExtraData["accesstoken"],
                    OAuthAccessToken = authResult.ProviderUserId,
                };

                if (_externalAuthenticationSettings.AutoRegisterEnabled)
                    ParseClaims(authResult, parameters);

                var result = _authorizer.AppAuthorize(parameters);

                return new AuthorizeState(null, result);
            }
            
        }

        private void ParseClaims(AuthenticationResult authenticationResult, AndroidAuthenticationParameters parameters)
        {
            var claims = new UserClaims();
            claims.Contact = new ContactClaims();
            if (authenticationResult.ExtraData.ContainsKey("username"))
                claims.Contact.Email = authenticationResult.ExtraData["username"];
            claims.Name = new NameClaims();
            if (authenticationResult.ExtraData.ContainsKey("name"))
            {
                var name = authenticationResult.ExtraData["name"];
                if (!String.IsNullOrEmpty(name))
                {
                    var nameSplit = name.Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (nameSplit.Length >= 2)
                    {
                        claims.Name.First = nameSplit[0];
                        claims.Name.Last = nameSplit[1];
                    }
                    else
                    {
                        claims.Name.Last = nameSplit[0];
                    }
                }
            }
            parameters.AddClaim(claims);
        }
        #endregion
    }
}